package isssr.bean.utility;

import isssr.bean.entity.GoalStatus;
import isssr.bean.entity.OrganizationalGoal;
import isssr.bean.entity.Role;
import isssr.bean.entity.User;

import java.util.ArrayList;
import java.util.HashSet;

import org.hibernate.HibernateException;

public class DBPopulator {

	private static int staticSequenceNumber = 0;
	
	private OrganizationalGoal tempGoal = null;
	
	private ArrayList<Role> roleList = new ArrayList<Role>();
	private ArrayList<User> userList = new ArrayList<User>();
	private ArrayList<OrganizationalGoal> goalList = new ArrayList<OrganizationalGoal>();
	
	private int getNextSequenceNumber()
	{
		int nextSequenceNumber = staticSequenceNumber;
		staticSequenceNumber += 1;
		if(staticSequenceNumber<nextSequenceNumber)
			System.out.println("Constrain fail");
		return nextSequenceNumber;
	}
	
	private Role createRole(Integer level, Boolean ownerPermission)
	{
		Role role = new Role();
		
		role.setTitle("Role_" + getNextSequenceNumber());
		role.setDescription("Description_" + getNextSequenceNumber());
		role.setLevel(new Integer(level));
		role.setGoalOwnerPermission(ownerPermission);
		
		return role ;
	}
	
	private Role createRole()
	{
		return createRole(new Integer(50), new Boolean(false));
	}
	
	private User createUser(Role role)
	{
		User user = new User();
		
		user.setFirstName("firstName_" + getNextSequenceNumber());
		user.setLastName("lastName_" + getNextSequenceNumber());
		user.setEmail("email" + getNextSequenceNumber() + "@mail.com");
		user.setUsername("username_" + getNextSequenceNumber());
		user.setPassword("password_" + getNextSequenceNumber());
		user.setRole(role);
		
		return user;
	}
	
	private User createOwner()
	{
		Boolean permission = new Boolean(true);
		Integer level = new Integer(20);
		
		Role role = createRole(level, permission);
		
		return createUser(role);
	}
	
	private User createEnactor()
	{
		Boolean permission = new Boolean(false);
		Integer level = new Integer(10);
		
		Role role = createRole(level, permission);
		
		return createUser(role);
	}
	
	private User createSuper()
	{
		Boolean permission = new Boolean(false);
		Integer level = new Integer(29);
		
		Role role = createRole(level, permission);
		
		return createUser(role);
	}
	
	private OrganizationalGoal createGoal(User owner)
	{
		OrganizationalGoal goal = new OrganizationalGoal();
		
		goal.setTitle("GoalTitle_" + getNextSequenceNumber());
		goal.setFocus("Focus_" + getNextSequenceNumber());
		goal.setConstraints("Constraints_" + getNextSequenceNumber());
		goal.setDescription("Description_" + getNextSequenceNumber());
		goal.setMagnitude("Magntude_" + getNextSequenceNumber());
		goal.setObject("Object_" + getNextSequenceNumber());
		goal.setOrganizationalScope("OrganizationalScope_" + getNextSequenceNumber());
		goal.setPriority(new Integer(getNextSequenceNumber()));
		goal.setStatus(GoalStatus.ELICITATION);
		goal.setTimeframe("Timeframe_" + getNextSequenceNumber());
		
		goal.setGoalOwner(owner);
		
		return goal;
	}
	
	private HashSet<User> createSuperList(int how_many)
	{
		HashSet<User> superList = new HashSet<User>();
		User zuper;
		
		for(int i=0; i<how_many; i++)
		{
			zuper = createSuper();
			superList.add(zuper);
		}
		
		return superList;
	}

	private HashSet<User> createSuperList() 
	{
		return createSuperList(5);
	}

	private void persistRole(Role role) throws HibernateException
	{
		try
		{
			role.save();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		
		this.roleList.add(role);
	}
	
	private void persistUser(User user) throws HibernateException
	{
		try
		{
			user.save();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		
		this.userList.add(user);
	}
	
	private void persistGoal(OrganizationalGoal goal) throws HibernateException
	{
		try
		{
			goal.save();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		this.goalList.add(goal);
	}
	
	
	private User createPersistentOwner()
	{
		User owner = createOwner();
		persistRole(owner.getRole());
		persistUser(owner);
		return owner;
	}
	
	private User createPersistentEnactor()
	{
		User enactor = createEnactor();
		persistRole(enactor.getRole());
		persistUser(enactor);
		return enactor;
	}
	
	private User createPersistentSuper()
	{
		User zuper = createSuper();
		persistRole(zuper.getRole());
		persistUser(zuper);
		return zuper;
	}
	
	private HashSet<User> createPersistentSuperList(int how_many)
	{
		HashSet<User> superList = new HashSet<User>();
		User zuper;
		
		for(int i=0; i<how_many; i++)
		{
			zuper = createPersistentSuper();
			superList.add(zuper);
		}
		return superList;
	}
	
	private HashSet<User> createPersistentSuperList()
	{
		return createPersistentSuperList(5);
	}
	
	public User pickRandomUser()
	{
		int randomUserPick = (int) (Math.random()*userList.size());
		
		return userList.get(randomUserPick);
	}
	

	private void setTempGoal(OrganizationalGoal goal)
	{
		this.tempGoal = goal;
		return;
	}
	
	public void populateDB()
	{
		Role role;
		User user;
		OrganizationalGoal goal;
		
		ArrayList<User> supers = new ArrayList<User>();
		ArrayList<User> owners = new ArrayList<User>();
		ArrayList<User> enactors = new ArrayList<User>();
		
		
		for(int i=0; i<10; i++)
		{	
			user = createPersistentEnactor();
			enactors.add(user);
			
		}
		for(int i=0; i<15; i++)
		{	
			user = createPersistentSuper();
			supers.add(user);
		}
		for(int i=0; i<5; i++)
		{	
			user = createPersistentOwner();
			owners.add(user);
		}
		
		int randomPickNumber = 0;
		int randomSizeNumber = 0;
		ArrayList<User> supersCopy = (ArrayList<User>) supers.clone();
		HashSet<User> chosenSuper;
		
		for(int i=0; i<10; i++)
		{
			randomPickNumber = (int) Math.random()*(owners.size());
			
			goal = createGoal(owners.get(randomPickNumber));
			
			randomSizeNumber = (int) Math.random()*(supers.size());
			
			chosenSuper = new HashSet<User>();
			
			for(int j=0 ; j<randomSizeNumber; j++)
			{
				randomPickNumber = (int) Math.random()*(supersCopy.size());
				user = supersCopy.remove(randomPickNumber);
				chosenSuper.add(user);
			}
			
			goal.setSuperList(chosenSuper);
			
			randomPickNumber = (int) Math.random()*(enactors.size());
			
			user = enactors.get(randomPickNumber);
			
			goal.setGoalEnactor(user);
			
			persistGoal(goal);
		}
		
		// a goal without supers or enactors
		
		user = createPersistentOwner();
		
		goal = createGoal(user);
		
		persistGoal(goal);
	}
	
	public void depopulateDB() throws HibernateException
	{
		if(this.tempGoal!=null)
		{
			try
			{
				this.tempGoal.unsave();
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
			this.tempGoal = null;
		}
		
		for(OrganizationalGoal g : this.goalList)
		{
			try{
			g.unsave();
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
				
			}
		}
		
		this.goalList.clear();
		
		for(User u: this.userList)
		{
			try{
			u.unsave();
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
		}
		
		this.userList.clear();
		
		for(Role r : this.roleList)
		{
			try{
			r.unsave();
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
		}
		
		this.roleList.clear();
		
	}
}
